﻿using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace Miziak_Custom_Client_Symulator
{
    class Memory
    {
        [Flags]
        private enum MemoryProtection
        {
            Execute = 0x10,
            ExecuteRead = 0x20,
            ExecuteReadWrite = 0x40,
            ExecuteWriteCopy = 0x80,
            NoAccess = 0x01,
            ReadOnly = 0x02,
            ReadWrite = 0x04,
            WriteCopy = 0x08,
            GuardModifierflag = 0x100,
            NoCacheModifierflag = 0x200,
            WriteCombineModifierflag = 0x400
        }

        public Memory() {}

        public bool checkTibia()
        {
            Process[] TibiaProcess = Process.GetProcessesByName("Tibia");
            if (TibiaProcess.Length != 0)
            {
                Process Tibia = TibiaProcess[0];
                hwnd = Tibia.MainWindowHandle;
                handle = Tibia.Handle;
                _base = Tibia.MainModule.BaseAddress.ToInt32();
                return true;
            }

            return false;
        }

        [DllImport("kernel32.dll")]
        private static extern Int32 ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
            [In, Out] byte[] buffer, UInt32 size, out IntPtr lpNumberOfBytesRead);

        [DllImport("kernel32.dll")]
        private static extern Int32 WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
            [In, Out] byte[] buffer, UInt32 size, out IntPtr lpNumberOfBytesWritten);

        [DllImport("kernel32.dll")]
        private static extern bool VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress,
            IntPtr dwSize, MemoryProtection flNewProtect, ref MemoryProtection lpflOldProtect);

        [DllImport("user32.dll")]
        private static extern bool SetWindowText(IntPtr hwnd, String lpString);

        private static bool WriteBytes(IntPtr handle, long address, byte[] bytes, uint length)
        {
            IntPtr bytesWritten;

            int result = WriteProcessMemory(handle, new IntPtr(address), bytes, length, out bytesWritten);
            return result != 0;
        }
        
        public bool WriteInt32(long address, int value)
        {
            address += (_base - 0x400000);
            return WriteBytes(handle, address, BitConverter.GetBytes(value), 4);
        }

        public bool WriteString(long address, string str)
        {
            address += (_base - 0x400000);
            str += '\0';
            byte[] bytes = System.Text.ASCIIEncoding.Default.GetBytes(str);
            return WriteBytes(handle, address, bytes, (uint)bytes.Length);
        }

        public bool writeRSA(long address)
        {
            IntPtr bytesWritten;
            int result;
            MemoryProtection oldProtection = 0;

            System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
            byte[] bytes = enc.GetBytes(RSA);

            VirtualProtectEx(handle, new IntPtr(address), new IntPtr(bytes.Length), MemoryProtection.ExecuteReadWrite, ref oldProtection);
            result = WriteProcessMemory(handle, new IntPtr(address), bytes, (uint)bytes.Length, out bytesWritten);
            VirtualProtectEx(handle, new IntPtr(address), new IntPtr(bytes.Length), oldProtection, ref oldProtection);

            return (result != 0);
        }

        public void setTitlebar(string title)
        {
            SetWindowText(hwnd, title);
        }

        private IntPtr handle;
        private IntPtr hwnd;
        private int _base;
        private static string RSA = "109120132967399429278860960508995541528237502902798129123468757937266291492576446330739696001110603907230888610072655818825358503429057592827629436413108566029093628212635953836686562675849720620786279431090218017681061521755056710823876476444260558147179707119674283982419152118103759076030616683978566631413";
    }
}
